package com.bird.common.utils;

import cn.hutool.log.Log;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.bird.common.constant.Constants;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 客户端工具类
 *
 * @author ym
 */
public class ServletUtil extends cn.hutool.extra.servlet.ServletUtil {

	private final static Log LOG = Log.get();

	/**
	 * 获取request
	 */
	public static HttpServletRequest getRequest() {
		return getRequestAttributes().getRequest();
	}

	/**
	 * 获取response
	 */
	public static HttpServletResponse getResponse() {
		return getRequestAttributes().getResponse();
	}

	/**
	 * 获取session
	 */
	public static HttpSession getSession() {
		return getRequest().getSession();
	}

	public static ServletRequestAttributes getRequestAttributes() {
		RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
		return (ServletRequestAttributes) attributes;
	}

	/**
	 * 获取String参数
	 */
	public static String getParameter(String name) {
		return getRequest().getParameter(name);
	}

	/**
	 * 获取Integer参数
	 */
	public static Integer getParameterToInt(String name) {
		String parameter = getRequest().getParameter(name);
		if (parameter == null) {
			return null;
		}
		return Integer.valueOf(parameter);
	}

	/**
	 * 获取Integer参数
	 */
	public static Integer getParameterToInt(String name, Integer defaultValue) {
		return Integer.valueOf(getRequest().getParameter(name), defaultValue);
	}

	/**
	 * 获取String参数
	 */
	public static String getHeader(String name) {
		return getRequest().getHeader(name);
	}

	/**
	 * 向web输出内容
	 *
	 * @param response
	 * @param obj
	 * @param contentType
	 * @throws Exception
	 */
	public static void write(HttpServletResponse response, Object obj, String contentType) {
		try {
			response.setContentType(contentType);
			PrintWriter writer = response.getWriter();
			writer.print(JSONObject.toJSONString(obj, SerializerFeature.WriteMapNullValue,
					SerializerFeature.WriteDateUseDateFormat));
			writer.close();
			response.flushBuffer();
		} catch (IOException e) {
			LOG.error(e);
		}
	}

	/**
	 * 获取get参数，字符串
	 *
	 * @param request
	 * @return
	 * @throws IOException
	 */
	public static String getParamString(HttpServletRequest request) {
		Map<String, String[]> parameterMap = request.getParameterMap();
		Map<String, String[]> sortedMap = parameterMap.entrySet().stream()
				.sorted(Map.Entry.comparingByKey())
				.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
						(oldValue, newValue) -> oldValue, LinkedHashMap::new));
		StringBuilder param = new StringBuilder();
		for (Map.Entry<String, String[]> entry : sortedMap.entrySet()) {
			String key = entry.getKey();
			String[] value = entry.getValue();
			param.append(key + "=");
			if (!ArrayUtils.isEmpty(value) && StringUtils.isNotBlank(value[0])) {
				param.append(value[0]);
			}
			param.append("&");
		}
		if (param.length() > 0) {
			param.deleteCharAt(param.lastIndexOf("&"));
		}
		return param.toString();
	}

	/**
	 * json 转 form-data格式
	 *
	 * @param request
	 * @return
	 */
	public static String getBodyToParamString(HttpServletRequest request) {
		String body = ServletUtil.getBody(request);
		if (StringUtil.isBlank(body)) {
			return null;
		}
		boolean valid = JSONObject.isValid(body);
		if (!valid) {
			return body;
		}
		JSONObject json = JSONObject.parseObject(body);
		Map<String, Object> sortedMap = json.entrySet().stream()
				.sorted(Map.Entry.comparingByKey())
				.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
						(oldValue, newValue) -> oldValue, LinkedHashMap::new));
		StringBuilder param = new StringBuilder();
		for (Map.Entry<String, Object> entry : sortedMap.entrySet()) {
			String key = entry.getKey();
			String value = (String) entry.getValue();
			param.append(key + "=");
			if (value != null) {
				param.append(value);
			}
			param.append("&");
		}
		if (param.length() > 0) {
			param.deleteCharAt(param.lastIndexOf("&"));
		}
		try {
			return URLEncoder.encode(param.toString(), "utf-8");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}

	/**
	 * 下载文件名重新编码
	 *
	 * @param fileName 文件名
	 * @return 编码后的文件名
	 */
	public static String setFileDownloadHeader(String fileName) {
		String filename = null;
		try {
			final String agent = getRequest().getHeader("USER-AGENT");
			filename = fileName;
			if (agent.contains(Constants.BrowserType.MSIE)) {
				// IE浏览器
				filename = URLEncoder.encode(filename, "utf-8");
				filename = filename.replace("+", " ");
			} else if (agent.contains(Constants.BrowserType.FIREFOX)) {
				// 火狐浏览器
				filename = new String(fileName.getBytes(), "ISO8859-1");
			} else if (agent.contains(Constants.BrowserType.CHROME)) {
				// google浏览器
				filename = URLEncoder.encode(filename, "utf-8");
			} else {
				// 其它浏览器
				filename = URLEncoder.encode(filename, "utf-8");
			}
		} catch (UnsupportedEncodingException e) {
			LOG.error(e);
		}
		return filename;
	}

	/**
	 * 导出excel
	 *
	 * @param fileName
	 * @return
	 */
	public static void exportExcel(Workbook workbook, String fileName) {
		HttpServletResponse response = ServletUtil.getResponse();
		response.setContentType("application/vnd.ms-excel");
		response.setCharacterEncoding("utf-8");
		response.setHeader("Content-disposition", "attachment; filename=" + setFileDownloadHeader(fileName));
		try (
				ServletOutputStream out = response.getOutputStream();
		) {
			workbook.write(out);
			workbook.close();
		} catch (Exception e) {
			LOG.error(e);
		}
	}
}
